<template>
  <div>
    <!--li drag 是拖拽事件-->
    <ul>
      <li draggable="true" @dragstart.stop="handleDragStart($event)"
          @dragenter="handleDragEnter" @dragleave="handleDragLeave"
          @dragover.prevent="handleDragOver" @drop.stop="handleDrop($event)" @dragend.prevent="handleDragEnd"
          class="nodeLi">
        <!--滑过节点显示功能点-->
        <div @mouseenter="showOprators" @mouseleave="hideOprators" class="columns" style="width: 220px">
          <div class="column">
            <a @click="toggle">
              <oolongIcon :type="open?'android-arrow-dropdown-circle':'android-arrow-dropright-circle'" size="30"
                          v-if="isFolder"></oolongIcon>
            </a>
          </div>
          <div class="column">
            <a @click="editNode">
              <oolongIcon type="compose" size="30"></oolongIcon>
            </a>
          </div>
          <div class="column nodeName">
            <a @dblclick="showDetail()" v-if="showInput">{{node.name}}</a>
            <input type="text" v-model="node.name" @keyup.enter="editorName" v-else/>
          </div>
          <div class="column" v-show="node.showSelect">
            <input type="checkbox" v-model="node.isCheck" @change="selectCheck" :id="node.id" class="noCss"
                   :disabled="node.isDisabled"/>
            <label :for="node.id"
                   :class="[{'check':node.isCheck,'indeterminate':node.indeterminate},'unCheck']"></label>
            <!--<input type="checkbox" v-model="node.selectCheck" @change="selectCh" :id="node.id"/>  -->
            <!--<input type="checkbox" v-model="node.selectDo" @change="selectDo" :id="node.id"/>  -->
          </div>
          <div class="column">
            <div class="columns" v-show="node.addNoBtn">
              <div class="column">
                <a @click="addSonNode">
                  <oolongIcon type="plus-circled" size="30"></oolongIcon>
                </a>
              </div>
              <div class="column">
                <a @click="removeNode">
                  <oolongIcon type="trash-a" size="30"></oolongIcon>
                </a>
              </div>
            </div>
          </div>
        </div>
        <!--子节点的内容-->
        <ul v-show="open" v-if="isFolder">
          <tree-node v-for="nodeNode in node.menuChild" :tree-node="nodeNode" :key="nodeNode.id"
                     @passNode="accNode"></tree-node>
        </ul>
      </li>
    </ul>
  </div>
</template>
<style lang="scss">
  .nodeLi {
    margin: 10px 0 0 44px;
    a {
      color: #B377A5;
      :hover {
        color: #8391a5;
      }
    }
  }
  .nodeName {
    font-size: 20px;
  }
  .noCss {
    visibility: hidden;
    display: none
  }
  .unCheck {
    background: url("../resources/img/components/unCkeck.png") no-repeat;
    width: 24px;
    height: 24px;
    display: inline-block;
    vertical-align: -8px;
  }
  .check {
    background: url("../resources/img/components/check.png") no-repeat;
    width: 24px;
    height: 24px;
    display: inline-block;
    vertical-align: -8px;
  }
  .indeterminate {
    background: url("../resources/img/components/indeterminate.png") no-repeat;
    width: 24px;
    height: 24px;
    display: inline-block;
    vertical-align: -8px;
  }
  .nodeLi {
    margin: 0 26px 10px;
  }
  .spanNode {
    display: block;
    border-bottom: 1px solid #ccc;
    height: 36px;
    line-height: 36px;
  }
  .unfold, .addBrotherNode, .addSunNode, .removeNode {
    display: inline-block;
    width: 24px;
    height: 24px;
    vertical-align: -8px;
    background: url("../resources/img/components/unfold.png")
  }
  .addBrotherNode {
    background: url("../resources/img/components/addBrother.png")
  }
  .addSunNode {
    background: url("../resources/img/components/addChild.png")
  }
  .removeNode {
    background: url("../resources/img/components/remove.png")
  }
  .fold {
    transform: rotate(-90deg)
  }
</style>
<script>
  export default{
    data: function () {
      return {
        showInput: true,
        show_oprators: false,
        is_draged: false,
        open: false,
        node: this.treeNode
      }
    },
    name: 'tree-node',
    props: {
      treeNode: {
        type: Object,
        default: function () {
          return {}
        }
      }
    },
    //计算属性 判断节点是否展开
    computed: {
      isFolder: function () {
        return this.node.menuChild && this.node.menuChild.length
      },
    },
    methods: {
      //元素被放到了放置目标中触发
      handleDrop: function (e) {
        var vm = window.__drop_node__;
        this.$el.style.backgroundColor = '';
        vm.$el.style.backgroundColor = '';

        var __parent__ = this;
        while (__parent__ !== undefined) {
          if (__parent__ === vm) {
            return;
          }
          __parent__ = __parent__.$parent;
        }

        var current_node = vm.node;
        //console.log(JSON.stringify(vm.$parent.node.menuChild))
        vm.$parent.node.menuChild = vm.$parent.node.menuChild.filter(function (node) {
          //console.log(JSON.stringify(node))
          //console.log(JSON.stringify(current_node))
          //alert(node !== current_node)
          return node !== current_node;
        });
        //console.log(JSON.stringify(current_node))
        //console.log(JSON.stringify(this.node))
        current_node.pid = this.node.id;
        this.node.menuChild.push(current_node);
        var jsonNode = {bool: true, handleDrop: true, node: this.node};
        this.$emit("passNode", jsonNode)
      },
      //当拖动停止时，会触发事件
      handleDragEnd: function () {
        this.$el.style.backgroundColor = '';
      },
      // 按下鼠标键并开始移动鼠标时执行
      handleDragStart: function (e) {
        this.show = false;
        this.is_draged = true;
        window.__drop_node__ = this;
        this.$el.style.backgroundColor = 'yellow';
      },
      //有元素被拖动到放置目标上执行
      handleDragEnter: function () {
        if (!this.is_draged) this.$el.style.backgroundColor = "grey";
      },
      //在元素被拖出放置目标时触发
      handleDragLeave: function () {
        if (!this.is_draged) this.$el.style.backgroundColor = "";
      },
      //在被拖动的元素还在放置目标范围内移动时，会持续触发
      handleDragOver: function () {
      },

      showOprators: function () {
        this.show_oprators = true;
      },
      hideOprators: function () {
        this.show_oprators = false;
      },
      accNode(node){
        this.$emit("passNode", node)
//        console.log(JSON.stringify(node))
      },
      editorName(){
        var jsonNode = {bool: true, editorName: true, node: this.node};
//        console.log(JSON.stringify(jsonNode))
        this.$emit("passNode", jsonNode)
        this.showInput = true;
      },
      selectCh(){
        var jsonNode = {bool: true, selectCh: true, node: this.node};
        this.$emit("passNode", jsonNode)
      },
      selectDo(){
        var jsonNode = {bool: true, selectDo: true, node: this.node};
        this.$emit("passNode", jsonNode)
      },
      //添加节点事件
      addNode: function () {
        var jsonNode = {bool: true, addSon: true, node: this.node};
        this.$emit("passNode", jsonNode)

      },
      //添加兄弟节点事件
      addBrotherNode(){
        var jsonNode = {bool: true, addBro: true, node: this.node};
        this.$emit("passNode", jsonNode)
      },
      //添加兄弟节点事件
      addBrotherNode1(){
//        console.log(JSON.stringify(this.node))
        var jsonNode = {bool: true, addBro: true, node: this.node};
        this.$emit("passNode", jsonNode)
      },
      //添加节点事件
      removeNode: function () {
        if (confirm('Do you want to remove node: ' + this.node.name)) {
          var current_node = this.node;
          this.$parent.node.menuChild = this.$parent.node.menuChild.filter(function (node) {
            return node !== current_node;
          });
        }
        this.$emit("passNode", this.node)
      },
      addSonNode: function () {
        var name = prompt("Input the name of new node", "new node");
        if (!!name && !!name.trim()) {
          this.node.menuChild.push({name: name.trim(), isCheck: false, menuChild: []});
        }
        if (!this.open) {
          this.open = !this.open
        }
        this.$emit("passNode", this.node)

      },
      //编辑节点事件
      editNode: function () {
        var name = prompt("Input the name of new node", this.node.name);
        if (!!name && !!name.trim()) {
          this.node.name = name.trim();
          this.$emit("passNode", this.node)

        }
      },
      //双击展开节点事件
      toggle: function () {
        if (this.isFolder) {
          console.log(this.isFolder)
          this.open = !this.open
        }
      },
      //复选框点击事件
      selectCheck(){
        this.newSelect(this);
        var current_isCheck = this.node.isCheck;
        if (!current_isCheck) {
          // 当前节点复选框全选和全不选事件 处理当前节点的子节点
          this.selectFn(this.node);
          this.$emit("passNode", this.node)
        } else if (current_isCheck) {
          // 当前节点复选框全选和全不选事件 处理当前节点的子节点
          this.selectFn(this.node);
          this.$emit("passNode", this.node)
        }
        this.$emit("passNode", this.node)
      },
      //复选框全选和全不选事件 处理当前节点的子节点
      selectFn(obj){
        if (obj instanceof Object) {
          //判断当前节点是否有子节点
          if (obj.menuChild && obj.menuChild.length) {
            //当前节点有子节点则处理当前节点的子节点全选和不选
            for (var i = 0, len = obj.menuChild.length; i < len; i++) {
              if (obj.isCheck) {
                //当前节点的子节点全部选中
                obj.menuChild[i].isCheck = true;
              } else {
                //当前节点的子节点全不选
                obj.menuChild[i].isCheck = false;
              }
              //递归循环当前节点的子节点
              this.selectFn(obj.menuChild[i]);
            }
          }
        }
      },
      //通过当前节点找到父节点
      newSelect(obj){
        this.newSelectParent(obj.$parent)
      },
      //通过父节点对自身和子节点进行数据判断
      newSelectParent(obj){
        let i = 0;
        let j = 0;
        let k = 0;
        //判断当前节点的子节点 选中个数 和 不确定状态个数
        while (j < obj.node.menuChild.length) {
          if (obj.node.menuChild[j].isCheck == true) i++;
          if (obj.node.menuChild[j].indeterminate == true) k++;
          j++;
        }
        //如果当前节点的子节点 选中个数 为 当前节点下子节点的个数 设置 当前节点选中
        if (i == obj.node.menuChild.length && k == 0) {
          //为保证样式和数据同步，进行数据的反转后再恢复
          obj.node.indeterminate = false;
          obj.node.isCheck = false;
          obj.node.isCheck = true;

        } else if (i == 0 && k == 0) {
          //当前节点的子节点 选中个数 为 0   设置 当前节点为不选中
          //为保证样式和数据同步，进行数据的反转后再恢复
          obj.node.indeterminate = false;
          obj.node.isCheck = true;
          obj.node.isCheck = false;
        } else {
          //当前节点的子节点 选中个数 为 0 和 当前节点下子节点的个数之间 设置 当前节点为不确定状态
          //为保证样式和数据同步，进行数据的反转后再恢复
          obj.node.indeterminate = true;
          obj.node.isCheck = true;
          obj.node.isCheck = false;
        }
        //递归处理当前节点的父节点数
//        console.log("newSelectParent==="+JSON.stringify(obj.node))
        //如果有父节点则执行递归操作
        if (obj.$parent.node != undefined) {
          this.newSelectParent(obj.$parent)
        }
      },
      //当前节点不选中 当前子节点的父节点则不选 不确定选中事件
      selectNoAll(obj){
//        console.log("子节点不全选父节点则不选事件"+JSON.stringify(obj.node))
        //是否为根节点
        if (obj.node.pid != '0') {
          //点击的当前节点是否选中
          if (obj.node.isCheck == false) {
            //当前节点未选中，设置 当前节点的父节点不选中
            obj.$parent.node.isCheck = false;
            //循环当前节点的 父节点 的子节点
            for (let m = 0; m < obj.$parent.node.menuChild.length; m++) {
              //判断 当前节点的 父节点下 子节点中是否有不全选的情况
              if (obj.$parent.node.menuChild[m].isCheck == true || obj.$parent.node.menuChild[m].indeterminate == true) {
//                console.log(JSON.stringify(obj.$parent.node))
                //设置 当前节点的父节点不确定选中
                obj.$parent.node.indeterminate = true;
                break;
              } else {
                //设置当前节点的父节点不确定状态为false
                obj.$parent.node.indeterminate = false;
              }
            }
            this.selectNoAll(obj.$parent);
          } else {
            return;
          }
        } else {
//          obj.node.indeterminate=false;
          let s = 0;
          //循环当前节点的 父节点下 的 子节点 ，判断当前节点的 父节点下子节点是否全选，当前节点的父节点选中
          while (obj.node.menuChild[s].isCheck == true) {
            s++;
            //判断当前节点的 父节点下子节点是否全选， 如果全选中则当前节点的父节点选中
            if (s == obj.node.menuChild.length) {
              obj.node.isCheck = true;
              obj.node.indeterminate = false;
              s = 0;
              return;
            }
          }
        }
      },
      //当前节点复选框 选中 判断当前节点的父节是否选中事件
      selectParent(obj){
//        console.log(JSON.stringify(obj.node))
        if (obj.node.pid != '0') {
          var i = 0;
          //判断当前节点是否选中
          if (obj.node.isCheck == true) {
            //设置当前节点不确定状态为false
            obj.node.indeterminate = false;
            //当前节点的父节点下子节点循环判断
            for (let n = 0; n < obj.$parent.node.menuChild.length; n++) {
              //如果当前节点的父节点下子节点有未选中 则设置当前节点的父节点为不确定选中状态
              if (obj.$parent.node.menuChild[n].isCheck == false) {
                obj.$parent.node.indeterminate = true;
                //如果当前节点的父节点 还有父节点 则设置 当前节点的父节点的父节点 为不确定状态
                if (obj.$parent.$parent.node) {
                  obj.$parent.$parent.node.indeterminate = true;
                }
                return;
              }
            }
            //当前节点的父节点下子节点 是否选中判断
            while (obj.$parent.node.menuChild[i].isCheck == true) {
              i++;
              //如果当前节点的父节点下子节点全部选中则选中父节点
              if (i == obj.$parent.node.menuChild.length) {
                obj.$parent.node.isCheck = true;
                obj.$parent.node.indeterminate = false;
                i = 0;
                //console.log(JSON.stringify(obj.$parent.node))
                this.selectParent(obj.$parent);
                return;
              } else {
                //如果当前节点的父节点下子节点不全部选中则 设置当前节点的父节点 为不确定状态
                obj.$parent.node.indeterminate = true;
              }
            }
          }
        }
      },
      //双击事件点击传输节点数据
      showDetail() {
        this.showInput = false;
      },
      dealWithData(obj){
        if (obj && obj.length) {
          for (var i = 0, len = obj.length; i < len; i++) {
            if (obj[i] instanceof Object) {
              if (!obj[i].indeterminate) obj[i]["indeterminate"] = false;
              if (!obj[i].selectCheck) obj["selectCheck"] = false;
              if (!obj[i].showSelect) obj[i]["showSelect"] = true;
              if (!obj[i].selectDo) obj[i]["selectDo"] = false;
              if (!obj[i].addNoBtn) obj[i]["addNoBtn"] = false;
              if (!obj[i].isCheck) obj[i]["isCheck"] = false;
              if (!obj[i].index) obj[i]["index"] = 0;
              this.dealWithData(obj[i].menuChild);
            }
          }
        } else if (obj instanceof Object) {
          if (!obj.indeterminate) obj["indeterminate"] = false;
          if (!obj.selectCheck) obj["selectCheck"] = false;
          if (!obj.showSelect) obj["showSelect"] = true;
          if (!obj.selectDo) obj["selectDo"] = false;
          if (!obj.addNoBtn) obj["addNoBtn"] = true;
          if (!obj.isCheck) obj["isCheck"] = false;
          if (!obj.index) obj["index"] = 0;
          if (obj.menuChild && obj.menuChild.length) {
            for (var i = 0; i < obj.menuChild.length; i++) {
              this.dealWithData(obj.menuChild[i]);
            }
          }
        }
        return obj;
      }
    },
    watch: {
      //监控传输过来的数据的变化 ， 将最新的数据赋值给data数据中的node
      treeNode(val){
        this.node = val;
      }
    }
  }
</script>
